/*
 * TODO language 
 * Copyright (c) 2010 TODO Team
 * 
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

#include <iostream>
#include "vm.h"
#include "types.h"
#include "internal.h"

namespace todo {
	
Scope::~Scope()
{
	variable_map::iterator it = variables.begin();
	func_map::iterator it2 = functions.begin();
	variable_map::iterator lastvar = variables.end();
	func_map::iterator lastfunc = functions.end();
	
	// Delete the variables
	for (; it != lastvar; ++it) {
		if (it->second->free) {
			it->second->data->data->type->dealloc(it->second->data->data);
			delete it->second->data;
		}
		delete it->second;
	}
	// Delete the functions
	for (; it2 != lastfunc; ++it2) {
		delete it2->second;
	}
	variables.clear();
	functions.clear();
}

/**
 * Adds a new scope
 */
void Scopes::add(Scope* scope)
{
	scopes.push_back(scope);
	// Sets the current scope
	Cscope = scope;
}

/**
 * Sets the global scope
 */
void Scopes::set_global(Scope* scope)
{
	Gscope = scope;
}

/**
 * Pops scope
 */
void Scopes::pop(void)
{
	Cscope = scopes[scopes.size()-1];	
}

Scopes::~Scopes(void)
{
	for (scopes_t::iterator it = scopes.begin(); it != scopes.end(); ++it) {
		delete (Scope*)*it;
	}
}

/**
 * Fetches the Value* according to argument list data type
 * @param context the Engine instance
 */
ArgValues* ArgList::get_values(todo::vm::Engine* context)
{
	ArgValues* values = new ArgValues;
	unsigned int argsize = args.size();
	
	for (unsigned int i = 0, j = argsize; i < j; ++i) {
		values->args.push_back(context->get_value(args[i]));
	}
	return values;
}

/**
 * Clear the argument list
 */
void ArgList::clear(void)
{
	arglist_t::iterator it;
	arglist_t::iterator lastarg = args.end();
	
	for (it = args.begin(); it != lastarg; ++it) {
		if ((*it)->data_type != TODO_RET_VALUE) {
			(*it)->data->type->dealloc((*it)->data);
		}
		delete *it;
	}
	args.clear();
}

void FunctionArgList::clear(void)
{
	funcargs_t::iterator it;
	funcargs_t::iterator lastfunc = args.end();
	
	for (it = args.begin(); it != lastfunc; ++it) {
		delete *it;	
	}
	args.clear();
}

/**
 * The static method representation
 * @param flags_ the method flags
 * @param ret_ the return type
 * @param name_ the method name
 * @param nparams the number of required parameters
 * @param param_types the list of pointer to param types
 * @param ptr_ the member pointer
 */
StaticMethod::StaticMethod(long flags_, const std::string& ret_, const std::string& name_, int n_params, Type** params_, StaticMethodPtr ptr_) :
		MethodBase(flags_ | TODO_STATIC, name_, n_params, params_), ptr(ptr_) 
{
	return_type = typeman.get_type(ret_);
}

/**
 * The method representation
 * @param flags_ the method flags
 * @param ret_ the return type
 * @param name_ the method name
 * @param nparams the number of required parameters
 * @param param_types the list of pointer to param types
 * @param ptr_ the member pointer
 */
Method::Method(long flags_, const std::string& ret_, const std::string& name_, int n_params, Type** params_, MethodPtr ptr_) :
		MethodBase(flags_, name_, n_params, params_), ptr(ptr_)
{
	return_type = typeman.get_type(ret_);
}

/**
 * The method representation
 * @param flags_ the method flags
 * @param ret_ the return type
 * @param name_ the method name
 * @param nparams the number of required parameters
 * @param param_types the list of pointer to param types
 * @param ptr_ the member pointer
 */
Method::Method(long flags_, Type* ret_, const std::string& name_, int n_params, Type** params_, MethodPtr ptr_) :
		MethodBase(flags_, name_, n_params, params_), ptr(ptr_)
{
	return_type = ret_;
}

} // todo
